package org.codehaus.activemq.message;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import javax.jms.JMSException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class WireFormat
{
  private static final Log log = LogFactory.getLog(WireFormat.class);

  public abstract Packet readPacket(DataInput paramDataInput)
    throws IOException;

  public abstract Packet readPacket(int paramInt, DataInput paramDataInput)
    throws IOException;

  public Packet readPacket(String channelID, DatagramPacket dpacket)
    throws IOException
  {
    DataInput in = new DataInputStream(new ByteArrayInputStream(dpacket.getData(), dpacket.getOffset(), dpacket.getLength()));
    String id = in.readUTF();

    if (channelID == null) {
      log.trace("We do not have a channelID which is probably caused by a synchronization issue, we're receiving messages before we're fully initialised");
    }
    else if (channelID.equals(id)) {
      if (log.isTraceEnabled()) {
        log.trace("Discarding packet from id: " + id);
      }
      return null;
    }
    int type = in.readByte();
    Packet packet = readPacket(type, in);

    return packet;
  }

  public abstract void writePacket(Packet paramPacket, DataOutput paramDataOutput)
    throws IOException, JMSException;

  public DatagramPacket writePacket(String channelID, Packet packet)
    throws IOException, JMSException
  {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    DataOutputStream dataOut = new DataOutputStream(out);
    dataOut.writeUTF(channelID);

    writePacket(packet, dataOut);
    dataOut.close();
    byte[] data = out.toByteArray();
    return new DatagramPacket(data, data.length);
  }

  public Packet fromBytes(byte[] bytes, int offset, int length)
    throws IOException
  {
    DataInput in = new DataInputStream(new ByteArrayInputStream(bytes, offset, length));
    return readPacket(in);
  }

  public Packet fromBytes(byte[] bytes)
    throws IOException
  {
    DataInput in = new DataInputStream(new ByteArrayInputStream(bytes));
    return readPacket(in);
  }

  public byte[] toBytes(Packet packet)
    throws IOException, JMSException
  {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    DataOutputStream dataOut = new DataOutputStream(out);
    writePacket(packet, dataOut);
    dataOut.close();
    return out.toByteArray();
  }

  public abstract WireFormat copy();
}